package cn.li.security.json.filter;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AndRequestMatcher;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class UsernamePasswordJSONAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
    public static final RequestMatcher APPLICATION_JSON_MATCHER = new MediaTypeRequestMatcher(new HeaderContentTyepNegotiationStrategy(),MediaType.APPLICATION_JSON);

    private ObjectMapper objectMapper;

    public UsernamePasswordJSONAuthenticationFilter(String pattern,ObjectMapper objectMapper) {
        super();
        this.objectMapper = objectMapper;
        RequestMatcher urlMatcher = new AntPathRequestMatcher(pattern, "POST");
        this.setRequiresAuthenticationRequestMatcher(
                //对请求URL限定，对请求数据报格式限定
               new AndRequestMatcher( urlMatcher,   APPLICATION_JSON_MATCHER)
        );
    }


    //缓存一下解析出来的body
    private Map<String,String> requestBody = new HashMap<>();
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        try {
            requestBody = objectMapper.readValue(request.getInputStream(),new TypeReference<Map<String,String>>(){});
        } catch (IOException e) {
            e.printStackTrace();
        }
        return super.attemptAuthentication(request,response);
    }

    @Nullable
    protected String obtainPassword(HttpServletRequest request) {
        return this.requestBody.get(this.getPasswordParameter());
    }

    @Nullable
    protected String obtainUsername(HttpServletRequest request) {
        return  this.requestBody.get(this.getUsernameParameter());
    }
}
